#ifndef ENGINE_H
#define ENGINE_H

#include <vector> // for State stack
#include <sstream> // for setCaption
#include "InputSet.h" // for input
#include <SDL/SDL.h> // for SDL
#include <OgreRoot.h> // for OGRE root
#include <OgreConfigFile.h> // for OGRE resources
#include <OgreRenderWindow.h> // for OGRE window
#include <SDL/SDL_mixer.h>
#include <stdlib.h>
#include <time.h>
#include <SDL_net.h>
#include "NetworkHandler.h"
#include "NetworkServer.h"
#include "NetworkClient.h"

/*
================================================================
Game engine with a stack of game states:
http://gamedevgeek.com/tutorials/managing-game-states-in-c/
================================================================
*/

class Engine;

/*
================================================================

================================================================
*/
class State
{
public:
	virtual ~State() {}

	virtual void init( Engine* game ) = 0;
	virtual void cleanup( Engine* game ) = 0;

	virtual void input( Engine* game ) = 0;
	virtual void update( Engine* game ) = 0;
	virtual void draw( Engine* game ) = 0;

	virtual void setCaption( std::ostringstream& buffer ) = 0;

	// TODO: Mouse events...

protected:
	State() {}
};

/*
================================================================

================================================================
*/
class Engine
{
public: // Lifecycle
	Engine();
	~Engine();

public: // Run
	bool setVideoMode( const int wx, const int wy, const bool fullscreen );
	bool init(bool initSDL, NetworkHandler *serverHandler, NetworkHandler *clientHandler, bool amIAlsoServer);
	void cleanup();
	void run();

public: // State stack
	void pop();
	void push( State* s );
	void change( State* s );

private: // Game loop
	void pollInput();

	void input();
	void update();
	void draw();

	void setCaption();

private: // Members
	// Engine
	std::vector < State* > states;
	unsigned int frames_elapsed;
	bool quit;

public: // Members
	// Engine
	InputSet is1, is2;

	// SDL
	SDL_Surface* screen;

	// Ogre
	Ogre::String plugins_cfg;
	Ogre::String resources_cfg;

	Ogre::Root* root;
	Ogre::RenderWindow* window;
	
	//networking
	NetworkHandler *server;
	NetworkHandler *client;
	bool isServer;
};

#endif

